package com.qianfeng.jdbc.utils;


//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼            BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  


import com.alibaba.druid.pool.DruidDataSource;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

/**
 * Created by jackiechan on 2021/8/23 14:40
 * 使用连接池的方式
 * @author jackiechan
 * @version 1.0
 * @since 1.0
 */

public class DBUtils {
    private static DataSource dataSource;//连接池

    private static ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<>();

    /**
     * datasource 的 getter 方法
     * @return
     */
    public static DataSource getDataSource() {
        return dataSource;
    }

    /**
     * 这个是连接池的创建方式,将连接的获取方式从每次单独获取变成放入到连接池中
     */
    static {
        try {
            InputStream inputStream = DBUtils.class.getResourceAsStream("/jdbc.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            // Class.forName("com.mysql.jdbc.Driver");
            dataSource=new DruidDataSource();//创建了连接池
            //连接池中放的是连接
            //连接是不是需要地址, 用户名, 密码
            ((DruidDataSource) dataSource).setDriverClassName(properties.getProperty("jdbc.driver"));
            ((DruidDataSource) dataSource).setUsername(properties.getProperty("jdbc.username"));
            ((DruidDataSource) dataSource).setPassword(properties.getProperty("jdbc.password"));
            ((DruidDataSource) dataSource).setUrl(properties.getProperty("jdbc.url"));
            //我们学习线程池的时候 线程池好像有大小,连接池也有
            //连接池 core 数量,最大数量,空闲数量
            //core 数量指的是创建的时候直接创建多少个
            //最大数量,在 core 数量不满足的情况下向上扩容,但是最多扩容到多少个
            //空闲数量
            ((DruidDataSource) dataSource).setMinIdle(2);//只要剩下的小于 2 个就开始扩容
            ((DruidDataSource) dataSource).setMaxActive(100);//最多扩容到 100 个
            ((DruidDataSource) dataSource).setInitialSize(10);//开始的数量
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static Connection getConnection() throws Exception {
        //这里我们应该修改为从连接池中获取连接,和线程池一样,需要先有一个池
        Connection connection = connectionThreadLocal.get();//先从本地线程中获取
        if (connection == null) {
            connection = dataSource.getConnection();//没有从连接池中获取
            connectionThreadLocal.set(connection);//保存到连接池
        }
        return connection;
    }

    /**
     * 开启事务
     */
    public static void  beginTransaction() throws Exception {
        Connection connection = getConnection();
        connection.setAutoCommit(false);
    }

    public static void  commit() throws Exception {
        Connection connection = getConnection();
        connection.commit();
        connection.close();//需要关闭吗? 连接池中的 connection 重写了关闭方法,实际上是放回到了连接池中
        connectionThreadLocal.remove();
    }

    public static void  rollback() throws Exception {
        Connection connection = getConnection();
        connection.rollback();
        connection.close();//需要关闭吗? 连接池中的 connection 重写了关闭方法,实际上是放回到了连接池中
        connectionThreadLocal.remove();
    }


    public static void  relase() throws Exception {
        Connection connection = getConnection();
        connection.close();//需要关闭吗? 连接池中的 connection 重写了关闭方法,实际上是放回到了连接池中
        connectionThreadLocal.remove();
    }

}
